<?php
declare (strict_types=1);

namespace app\admin\controller\system;

use think\Response;
use app\common\utils\JwtUtils;
use app\common\enum\SystemEnum;
use app\common\utils\IpInfoUtils;
use hg\apidoc\annotation as Apidoc;
use think\db\exception\DbException;
use app\common\model\system\UserModel;
use app\common\cache\system\UserCache;
use app\common\controller\AdminController;
use app\common\validate\system\UserValidate;

/**
 * @Apidoc\Title("账户管理")
 * @Apidoc\Group("adminSystem")
 * @Apidoc\Sort("500")
 */
class User extends AdminController
{
    /**
     * 初始化方法
     * @return void
     */
    public function initialize(): void
    {
        parent::initialize();
        $this->model = new UserModel();
    }

    /**
     * @Apidoc\Title("列表")
     * @Apidoc\Param(ref="indexParam")
     * @Apidoc\Returned(ref="indexReturn")
     * @Apidoc\Returned("data", type="array", desc="内容列表",
     *     @Apidoc\Returned(ref="app\common\model\system\UserModel",withoutField="password")
     * )
     * @return Response
     * @throws DbException
     */
    public function index(): Response
    {
        [$page, $limit, $where, $order] = $this->buildSelect();
        $data = $this->model->where($where)->order($order)->paginate(['list_rows' => $limit, 'page' => $page]);
        return $this->result($data->isEmpty() ? [] : $data->toArray());
    }

    /**
     * @Apidoc\Title("添加")
     * @Apidoc\Method("POST")
     * @Apidoc\Param(ref="app\common\model\system\UserModel",withoutField="id,login_number,login_last_ip,login_last_ip_region,login_last_time,create_time,update_time,delete_time")
     * @Apidoc\Returned(ref="app\common\model\system\UserModel",withoutField="password")
     */
    public function add(): Response
    {
        $this->validate($this->param, UserValidate::class, 'add');
        $data = $this->model;
        $data->save($this->param);
        return $this->result($data->toArray());
    }

    /**
     * @Apidoc\Title("详情")
     * @Apidoc\Param(ref="app\common\model\system\UserModel",field="id")
     * @Apidoc\Returned(ref="app\common\model\system\UserModel",withoutField="password")
     */
    public function read(): Response
    {
        $this->validate($this->param, UserValidate::class, 'read');
        $data = UserCache::get($this->param['id']);
        if (empty($data)) {
            $data = $this->model->findOrEmpty($this->param['id']);
            if ($data->isEmpty()) {
                return $this->error(SystemEnum::DATA_NOT_EXIST);
            }
            $data = $data->toArray();
            UserCache::set($this->param['id'], $data);
        }
        return $this->result($data);
    }

    /**
     * @Apidoc\Title("修改")
     * @Apidoc\Method("POST")
     * @Apidoc\Param(ref="app\common\model\system\UserModel",withoutField="login_number,login_last_ip,login_last_ip_region,login_last_time,create_time,update_time,delete_time")
     * @Apidoc\Returned(ref="app\common\model\system\UserModel",withoutField="password")
     * @return Response
     */
    public function edit(): Response
    {
        $this->validate($this->param, UserValidate::class, 'edit');
        $data = $this->model->findOrEmpty($this->param['id']);
        if ($data->isEmpty()) {
            return $this->error(SystemEnum::EDIT_DATA_ERROR);
        } else {
            $data->save($this->param);
        }
        return $this->result($data->toArray());
    }

    /**
     * @Apidoc\Title("删除")
     * @Apidoc\Method("POST")
     * @Apidoc\Param("id",type="array|int",desc="主键ID")
     * @return Response
     */
    public function del(): Response
    {
        $this->validate($this->param, UserValidate::class, 'del');
        $data = $this->model->destroy($this->param['id']);
        if ($data) {
            return $this->result([]);
        }
        return $this->error(SystemEnum::DELETE_DATA_ERROR);
    }

    /**
     * NotHeaders
     * @Apidoc\Title("登录")
     * @Apidoc\Method("POST")
     * @Apidoc\Param(ref="app\common\model\system\UserModel",field="account,password")
     * @Apidoc\Returned(ref="app\common\model\system\UserModel",withoutField="password")
     * @Apidoc\Returned("token",type="string",desc="Token登录凭证")
     * @return Response
     */
    public function login(): Response
    {
        $this->validate($this->param, UserValidate::class, 'login');

        $where[]   = ['account', '=', $this->param['account']];
        $where[]   = ['is_disable', '=', 0];
        $user_info = $this->model->where($where)->findOrEmpty();
        if ($user_info->isEmpty()) {
            return $this->error(SystemEnum::ACCOUNT_NOT_EXIST);
        }
        if (md5($this->param['password']) != $user_info->getAttr('password')) {
            return $this->error(SystemEnum::INCORRECT_PASSWORD);
        }
        $ip_info                         = IpInfoUtils::getInfo();
        $user_info->login_number         = $user_info->login_number + 1;
        $user_info->login_last_ip        = $ip_info['ip'];
        $user_info->login_last_ip_region = $ip_info['country'] . $ip_info['province'] . $ip_info['city'] . $ip_info['region'] . $ip_info['isp'];
        $user_info->login_last_time      = date_time();
        $user_info->save();

        $data          = $user_info->toArray();
        $token_info    = [
            'system_user_id' => $data['id'],
            'login_time'     => $data['login_last_time'],
            'login_ip'       => $data['login_last_ip'],
        ];
        $system_config = get_sys_config('', 'token');
        $data['token'] = JwtUtils::createToken($token_info, intval($system_config['token_admin_expires']), $system_config['token_admin_key']);

        $cache_expires = intval($system_config['token_admin_expires']) * 3600;
        //将登录后的用户数据存入缓存
        UserCache::set($data['id'], $data, $cache_expires);
        return $this->result($data);
    }

    /**
     * @Apidoc\Title("退出")
     * @Apidoc\Method("POST")
     * @return Response
     */
    public function logout(): Response
    {
        $logout = UserCache::delete($this->token_info['system_user_id']);
        return $logout ? $this->result() : $this->error();
    }
}
